I øvelsen skal vi lære om debugging så vi har en bedre mulighed for at fejlsøge hvores programmer.
Vi benytter os af del 3 fra Øvelse 5
Del 1 Debugging using gdb
Når vi skal compile og bruge gdb ønsker vi at indsætte debug information, dette gøres ved:
Indsættelse af flags - O0 -g
Compileren som vi benytter er en traditionel C++ compiler for host: g++
g++ -O0 -g -o del3 del3.cpp -lpthreads
Herefter ønsker vi at debugge programmet. Dette gøres med kommandoen
gdb ./del3
Indsættelse af breakpoint
Vi har nu mulighed for at indsætte et breakpoint, dette gør vi ved
(gdb) b 12
Svaret der kommer ud fra dette er
Breakpoint 2 at 0x80488e3: file del3.cpp, line 12.
Vi kan nu se at vi har fået sat et breakpoint i linie 12
Vi kan få infromation om breakpoints i programmet med følgende kommando
info breakpoints
Herefter vil den udskrive de breakpoints vi har
Num Type Disp Enb Address What
1 breakpoint keep y 0x0804879a in write(void*) at del3.cpp:18
2 breakpoint keep y 0x080488e3 in __static_initialization_and_destruction_0(int, int) at del3.cpp:12
Ved at skrive
r kan vi køre programmet
Starting program: /home/stud/Dropbox/3_semester/ISU/Ovelser/Exercise_7/del3/del3
[Thread debugging using libthread_db enabled]
Breakpoint 2, __static_initialization_and_destruction_0 (__initialize_p=1,
__priority=65535) at del3.cpp:16
16 Vector vector1;
Vi kan få lavet en oversigt over vilke tråde der køre(bliver oprettet) dette gøres ved at skrive "info threads" eller "i threads"
Stjernen anviser hvilken tråd der bliver oprettet i denne eksekvering
Id Target Id Frame
* 1 Thread 0xb7fe8af0 (LWP 2576) "del3" __static_initialization_and_destruction_0 (
__initialize_p=1, __priority=65535) at del3.cpp:16
Backtrace
Med backtrace kan vi få en oversigt over hvordan programmet er nået til punktet. Man bruger kommandoen "bt" for dette.
#0 __static_initialization_and_destruction_0 (__initialize_p=1, __priority=65535)
at del3.cpp:16
#1 0x08048928 in _GLOBAL__sub_I_sem () at del3.cpp:55
#2 0x08048b12 in __libc_csu_init ()
#3 0x002500aa in __libc_start_main (main=0x804881a <main()>, argc=1,
ubp_av=0xbfffed84, init=0x8048ac0 <__libc_csu_init>,
fini=0x8048b30 <__libc_csu_fini>, rtld_fini=0x11eba0, stack_end=0xbfffed7c)
at libc-start.c:185
#4 0x08048701 in _start ()
#0 viser hvor vi pt står i programmet og #1, #2 ... er den som har kaldt #0.
Segmentation fault
Hvis der laves en segmentation fault og programmet køres med gdb stopper denne automatisk og der oprettes et core dump der er lokaliseret i vores working directory, der bliver dog kun oprettet et core dump hvis core dump er blevet enabled. Ligeledes meddeler gdb at der er en fejl i programmets kode. Ved at skrive print og så fejlen kan man få mere info om hvad problemet er.
Del 2 - using DDD
DDD står for "Data Display Debugger".
Dette vil sige at den giver en grafisk brugerflade til gdb debuggeren :)
For at starte med DDD skrives blot
ddd del3
om det er f.eks. er en binær fil man vil køre skal der tilføres en ekstra parameter
dd --gdb del3
Det er muligt at bruge andre debuggere end gdb, men som udgangs punkt tildeler denne os med den info vi behøver omkring fejl i programmet.
Vi ser her vilke tråde programmet har kørende
Brug af breakpoint skriver den ud hvor dette sker
Backtrace viser ligesom i 1del af opgaven, hvordan programmet er kommet dertil hvor brakepointet er indsat:
Segmentation fault
er den samme som i 1.del
Del 3 Cross debugging
Opstart af gdb server
gdbserver localhost:1234 ./tgt_tgt
Efter dette startede vi gdb på host:
arm-angstrom-linux-gnueabi-gdb ./tgt_tgt
for at opnå en bedre debugging laves shell scriptettet
set solib-absolute-prefix /home/stud/setup-scripts/build/tmp-angstrom_2010_x-eglibc/sysroots/beagleboard
efter dette kunne i connecte til target med commandoen:
target remote 10.9.8.2:1234
Indsættelse af breakpoint
b main
for at køre programmet til breakpoint skal man bruge c. I modsætning til da vi kørte på host hvor det var r.
(gdb) b main
Breakpoint 1 at 0x883c
(gdb) c
Continuing.
Breakpoint 1, 0x0000883c in main ()
(gdb) c
Continuing.
[New Thread 1563]
[Inferior 1 (Remote target) exited normally]
vi kan se at breakpoint er sat ved adresse 0x883c
vi kan herefter køre programmet igennem og se afslutningen på programmet.
On target ser det ud som følgende:
Child exited with status 0
GDBserver exiting
root@beagleboard:/tmp#
Del 4 Core dumps
for at bruge core dumps benyttes :
ulimit -c unlimited
når vi så køre gdb og der opstår en core dump af den og den vil så blive vidst når vi køre
gdb ./del3 core
Fejlen som der udskrives kan se ud som følger:
Program terminated with signal 11 Segmentation fault.
#0 0x00009d09 in main() at del3.cpp:18
18 del3.cpp: No such file or directory.
in del3.cpp
Del 5 Core debugging using ddd
for at bruge ddd skrev vi følgende commando i terminalen
dd --debugger "arm-angstrom-linux-gnuabi-gdb"
Herefter skulle de samme to linier som vi skrev i gdb delen for debugging skrives for connecte til target og debugge
Del 6 Valgrind
Valgrind kan bruges til at checek for om der er memory leeks i programmet.
memory problem 1
vi vælger ikke at frigive hukommelsen efter brug
For at benytte valgrind skrives "valgrind ./del3"
Efter at programmet har kørt igennem komme følgende besked
==3039==
==3039== HEAP SUMMARY:
==3039== in use at exit: 28 bytes in 1 blocks
==3039== total heap usage: 12 allocs, 11 frees, 41,468 bytes allocated
==3039==
==3039== LEAK SUMMARY:
==3039== definitely lost: 0 bytes in 0 blocks
==3039== indirectly lost: 0 bytes in 0 blocks
==3039== possibly lost: 0 bytes in 0 blocks
==3039== still reachable: 28 bytes in 1 blocks
==3039== suppressed: 0 bytes in 0 blocks
==3039== Rerun with --leak-check=full to see details of leaked memory
==3039==
==3039== For counts of detected and suppressed errors, rerun with: -v
==3039== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 19 from 6)
vi kan her se at der stadig er hukommelse i brug efter afslutning af programmet.
memory problem 2
som vores memory prooblem to vælger vi et også yderst relevant problem nemlig at skrive mere data ind i et array end der er plads til
i dette tilfælde vælger vi at skrive 10000 ellementer ind i et array hvor der kun er plads til 1000.
stud@GoldenImage:~/ISU2/ovelse7/Debug$ valgrind --leak-check=full --show-reachable=yes ./ovelse7
==7473== Memcheck, a memory error detector
==7473== Copyright (C) 2002-2010, and GNU GPL'd, by Julian Seward et al.
==7473== Using Valgrind-3.6.1-Debian and LibVEX; rerun with -h for copyright info
==7473== Command: ./ovelse7
==7473==
==7473== Invalid write of size 4
==7473== at 0x8048A58: Vector::set(int) (Vector.hpp:57)
==7473== by 0x80489A4: Vector::Vector() (Vector.hpp:31)
==7473== by 0x80488EE: __static_initialization_and_destruction_0(int, int) (del3.cpp:16)
==7473== by 0x8048927: _GLOBAL__sub_I_sem (del3.cpp:55)
==7473== by 0x8048B11: __libc_csu_init (in /home/stud/ISU2/ovelse7/Debug/ovelse7)
==7473== by 0x41630A9: (below main) (libc-start.c:185)
==7473== Address 0x4313fc8 is 0 bytes after a block of size 4,000 alloc'd
==7473== at 0x4027F65: operator new[](unsigned int) (vg_replace_malloc.c:299)
==7473== by 0x8048989: Vector::Vector() (Vector.hpp:30)
==7473== by 0x80488EE: __static_initialization_and_destruction_0(int, int) (del3.cpp:16)
==7473== by 0x8048927: _GLOBAL__sub_I_sem (del3.cpp:55)
==7473== by 0x8048B11: __libc_csu_init (in /home/stud/ISU2/ovelse7/Debug/ovelse7)
==7473== by 0x41630A9: (below main) (libc-start.c:185)
==7473==
valgrind: m_mallocfree.c:225 (mk_plain_bszB): Assertion 'bszB != 0' failed.
valgrind: This is probably caused by your program erroneously writing past the
end of a heap block and corrupting heap metadata. If you fix any
invalid writes reported by Memcheck, this assertion failure will
probably go away. Please try that before reporting this as a bug.
Thread problem 1
i denne thread fejl glemmer vi at frigive låsen efter at denne er blevet taget dette medfører at programmet prøver at bruge en lås to gange på samme tid vilket fører til en fejl
==22527== Thread #2: Attempt to re-lock a non-recursive lock I already hold
==22527== at 0x4D2D226: pthread_mutex_lock (in /usr/lib/valgrind/vgpreload_helgrind-amd64-linux.so)
==22527== by 0x420EB1: ScopedLocker::ScopedLocker(pthread_mutex_t&) (scopeLocker.hpp:12)
==22527== by 0x420F84: Vector::setAndTest(int) (Vector.hpp:33)
==22527== by 0x420CB6: thread_function(void*) (del3.cpp:18)
==22527== Lock was previously acquired
==22527== at 0x4C2D33D: pthread_mutex_lock (in /usr/lib/valgrind/vgpreload_helgrind-amd64-linux.so)
==22527== by 0x420EB1: ScopedLocker::ScopedLocker(pthread_mutex_t&) (scopeLocker.hpp:12)
==22527== by 0x420F84: Vector::setAndTest(int) (Vector.hpp:33
Thread problem 2
i denne frigiver vi en lås der ikke er i brug
==23181== Thread #2 unlocked a not-locked lock at 0x601950
==23181== at 0x4C2D746: pthread_mutex_unlock (in /usr/lib/valgrind/vgpreload_helgrind-amd64-linux.so)
==23181== by 0x400EC8: ScopedLocker::~ScopedLocker() (scopeLocker.hpp:17)
==23181== by 0x400FBA: Vector::setAndTest(int) (Vector.hpp:35)
Thread problem 3
i den første thread fejl har vi en shared variable vi tilgår uden at have låsen
det er vigtigt at beskytte en shared variable med en lås så der ikke opstår en konflikt
==7624== Possible data race during write of size 4 at 0x4314028 by thread #3
==7624== at 0x8048974: Vector::set(int) (Vector.hpp:57)
==7624== by 0x804893F: Vector::setAndTest(int) (Vector.hpp:47)
==7624== by 0x8048735: write(void*) (del3.cpp:27)
==7624== by 0x4028F62: mythread_wrapper (hg_intercepts.c:221)
==7624== by 0x404AD30: start_thread (pthread_create.c:304)
==7624== by 0x421E46D: clone (clone.S:130)
==7624== This conflicts with a previous write of size 4 by thread #2
==7624== at 0x8048974: Vector::set(int) (Vector.hpp:57)
==7624== by 0x804893F: Vector::setAndTest(int) (Vector.hpp:47)
==7624== by 0x8048735: write(void*) (del3.cpp:27)
==7624== by 0x4028F62: mythread_wrapper (hg_intercepts.c:221)
==7624== by 0x404AD30: start_thread (pthread_create.c:304)
==7624== by 0x421E46D: clone (clone.S:130)
de valgte fejl er vigtige at forstå da det er nogle gennerelle fejl som man nemt kan overse mens man programmerer, ligeledes er det fejl som compejleren ikke tager fat i når programmet bliver compileret,
på trods af at det er fejl som under alle omstendigheder vil gørre at programmet ikke virker som det skal.
I øvelsen skal vi lære om debugging så vi har en bedre mulighed for at fejlsøge hvores programmer.
Vi benytter os af del 3 fra Øvelse 5
Del 1 Debugging using gdb
Når vi skal compile og bruge gdb ønsker vi at indsætte debug information, dette gøres ved:
Indsættelse af flags - O0 -g
Compileren som vi benytter er en traditionel C++ compiler for host: g++
Herefter ønsker vi at debugge programmet. Dette gøres med kommandoen
Indsættelse af breakpoint
Vi har nu mulighed for at indsætte et breakpoint, dette gør vi ved
Svaret der kommer ud fra dette er
Vi kan nu se at vi har fået sat et breakpoint i linie 12
Vi kan få infromation om breakpoints i programmet med følgende kommando
Herefter vil den udskrive de breakpoints vi har
Ved at skrive
r kan vi køre programmet
Starting program: /home/stud/Dropbox/3_semester/ISU/Ovelser/Exercise_7/del3/del3 [Thread debugging using libthread_db enabled] Breakpoint 2, __static_initialization_and_destruction_0 (__initialize_p=1, __priority=65535) at del3.cpp:16 16 Vector vector1;Vi kan få lavet en oversigt over vilke tråde der køre(bliver oprettet) dette gøres ved at skrive "info threads" eller "i threads"Stjernen anviser hvilken tråd der bliver oprettet i denne eksekvering
Id Target Id Frame * 1 Thread 0xb7fe8af0 (LWP 2576) "del3" __static_initialization_and_destruction_0 ( __initialize_p=1, __priority=65535) at del3.cpp:16BacktraceMed backtrace kan vi få en oversigt over hvordan programmet er nået til punktet. Man bruger kommandoen "bt" for dette.
#0 __static_initialization_and_destruction_0 (__initialize_p=1, __priority=65535) at del3.cpp:16 #1 0x08048928 in _GLOBAL__sub_I_sem () at del3.cpp:55 #2 0x08048b12 in __libc_csu_init () #3 0x002500aa in __libc_start_main (main=0x804881a <main()>, argc=1, ubp_av=0xbfffed84, init=0x8048ac0 <__libc_csu_init>, fini=0x8048b30 <__libc_csu_fini>, rtld_fini=0x11eba0, stack_end=0xbfffed7c) at libc-start.c:185 #4 0x08048701 in _start ()#0 viser hvor vi pt står i programmet og #1, #2 ... er den som har kaldt #0.Segmentation fault
Hvis der laves en segmentation fault og programmet køres med gdb stopper denne automatisk og der oprettes et core dump der er lokaliseret i vores working directory, der bliver dog kun oprettet et core dump hvis core dump er blevet enabled. Ligeledes meddeler gdb at der er en fejl i programmets kode. Ved at skrive print og så fejlen kan man få mere info om hvad problemet er.
Del 2 - using DDD
DDD står for "Data Display Debugger".
Dette vil sige at den giver en grafisk brugerflade til gdb debuggeren :)
For at starte med DDD skrives blot
om det er f.eks. er en binær fil man vil køre skal der tilføres en ekstra parameter
Det er muligt at bruge andre debuggere end gdb, men som udgangs punkt tildeler denne os med den info vi behøver omkring fejl i programmet.
Vi ser her vilke tråde programmet har kørende
Brug af breakpoint skriver den ud hvor dette sker
Backtrace viser ligesom i 1del af opgaven, hvordan programmet er kommet dertil hvor brakepointet er indsat:
Segmentation fault
er den samme som i 1.del
Del 3 Cross debugging
Opstart af gdb server
Efter dette startede vi gdb på host:
for at opnå en bedre debugging laves shell scriptettet
efter dette kunne i connecte til target med commandoen:
Indsættelse af breakpoint
for at køre programmet til breakpoint skal man bruge c. I modsætning til da vi kørte på host hvor det var r.
vi kan se at breakpoint er sat ved adresse 0x883c
vi kan herefter køre programmet igennem og se afslutningen på programmet.
On target ser det ud som følgende:
Del 4 Core dumps
for at bruge core dumps benyttes :
når vi så køre gdb og der opstår en core dump af den og den vil så blive vidst når vi køre
Fejlen som der udskrives kan se ud som følger:
Program terminated with signal 11 Segmentation fault. #0 0x00009d09 in main() at del3.cpp:18 18 del3.cpp: No such file or directory. in del3.cppDel 5 Core debugging using ddd
for at bruge ddd skrev vi følgende commando i terminalen
Herefter skulle de samme to linier som vi skrev i gdb delen for debugging skrives for connecte til target og debugge
Del 6 Valgrind
Valgrind kan bruges til at checek for om der er memory leeks i programmet.
memory problem 1
vi vælger ikke at frigive hukommelsen efter brug
For at benytte valgrind skrives "valgrind ./del3"
Efter at programmet har kørt igennem komme følgende besked
vi kan her se at der stadig er hukommelse i brug efter afslutning af programmet.
memory problem 2
som vores memory prooblem to vælger vi et også yderst relevant problem nemlig at skrive mere data ind i et array end der er plads til
i dette tilfælde vælger vi at skrive 10000 ellementer ind i et array hvor der kun er plads til 1000.
Thread problem 1
i denne thread fejl glemmer vi at frigive låsen efter at denne er blevet taget dette medfører at programmet prøver at bruge en lås to gange på samme tid vilket fører til en fejl
Thread problem 2
i denne frigiver vi en lås der ikke er i brug
Thread problem 3
i den første thread fejl har vi en shared variable vi tilgår uden at have låsen
det er vigtigt at beskytte en shared variable med en lås så der ikke opstår en konflikt
de valgte fejl er vigtige at forstå da det er nogle gennerelle fejl som man nemt kan overse mens man programmerer, ligeledes er det fejl som compejleren ikke tager fat i når programmet bliver compileret,
på trods af at det er fejl som under alle omstendigheder vil gørre at programmet ikke virker som det skal.
code
code
Thread problem 2